home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 108_01 / compress.c < prev    next >
Text File  |  1985-11-13  |  14KB  |  485 lines

  1. /*
  2. **    compress.c    Version 2.2
  3. **
  4. **    Version 2.2    15-Aug-80
  5. **
  6. **    this program compresses/expands any valid ASCII text
  7. **    file. the CP/M CRLF sequence is replaced by NL, and
  8. **    strings of identical characters of greater than 3 bytes
  9. **    are reduced to 3 bytes in the following format:
  10. **
  11. **        byte 1:    repeat code    RCODE    000Q
  12. **        byte 2: repeat count    cntr    ---Q
  13. **        byte 3:    character    c    ---Q
  14. **
  15. **    in addition, the most common key-words of various
  16. **    languages (BASIC, ASSEMBLER, FORTRAN, etc.), as
  17. **    well as a number of miscellaneous strings, are
  18. **    tokenized to 1 byte. the average total disk space
  19. **    saved is approximately 20%. processing time is
  20. **    approximately 30" for a 10K file with read-after-
  21. **    write (RAW) in a 40K system.
  22. **
  23. **    considerable protection has been built in to avoid
  24. **    such disasters as compressing a compressed file or
  25. **    expanding an ordinary file - see COMPRESS.DOC for
  26. **    complete details.
  27. **
  28. **    all files processed with earlier versions will be 
  29. **    processed coorectly by this version.
  30. **
  31. **    A>compress {dev:}filename.ext /switch
  32. **
  33. **    /c compress file
  34. **    /e expand file
  35. **
  36. **    NOTE: the system size (example 32K, 40K etc.) should
  37. **          be set as the defined value for SYSIZE. the
  38. **          greater the size of the working buffer, the
  39. **          faster the process will execute.
  40. */
  41.  
  42. #include <stdef.c>
  43.  
  44. #define    STRCOUNT 157        /* size of string array    */
  45. #define    STRSIZE     9
  46.  
  47. #define    SYSIZE    40        /* system size        */
  48. #define    MAXFILE    SYSIZE-30
  49. #define    BUFSIZE    (MAXFILE+1)*K
  50. #define    TOPBUF    BUFSIZE-256
  51.  
  52. #define    TRUE    -1
  53. #define    FALSE    0
  54. #define    RCODE    0
  55. #define    NULL    '\0'
  56. #define    SYN    22
  57. #define    FS    28
  58. #define    LLIMIT    ' '
  59. #define    INT_EOS    '|'
  60. #define    HLIMIT    '~'
  61.  
  62. #define    OFFSET1    99
  63. #define    OFFSET2    1
  64. #define    OFFSET3    3
  65. #define    OFFSET4    4
  66.  
  67. #define ARGCOUNT 3
  68. #define    MAXEXT    13
  69. #define    COMPRESS 'C'
  70. #define EXPAND   'E'
  71.  
  72. #define    ABRTMSG "aborting..."
  73. #define    ARGCERR    "too many/few arguments"
  74. #define    BINMSG  "  warning: possible binary file, continue (y/n) <abort>: "
  75. #define    CLOSERR    "cannot close output file"
  76. #define    IEXTERR    "illegal .EXT for this operation"
  77. #define    INPFERR    "cannot open input file"
  78. #define    NIMPERR    ".EXT not implemented"
  79. #define    OUTFERR    "cannot open output file"
  80. #define    SWITERR    "illegal switch"
  81.  
  82. char wrdbuf[STRCOUNT][STRSIZE];
  83. char rambuf[BUFSIZE], *bufpntr;
  84. char inbuf[134], outbuf[134];
  85. char expbuf[MAXEXT][4], cmpbuf[MAXEXT][4];
  86.  
  87. char ofname[12], ext[4];
  88. unsigned charcntr;
  89.  
  90. main(argc,argv)
  91. char **argv;
  92. int argc;
  93. {
  94.     char *mode ; mode  = &argv[2][1];
  95.     char *ifname; ifname = *++argv;
  96.     int filedescr;
  97.  
  98.     if (argc != ARGCOUNT) error(ARGCERR);
  99.  
  100.     initbuf(); filedescr = openout(ifname,mode);
  101.     getfile(ifname,mode); wrbuf();
  102.     closeout(filedescr); unlink(ifname);
  103. }
  104.  
  105. /*
  106. **    read the contents of the file into the input
  107. **    buffer and process.
  108. */
  109. getfile(ifname,mode)
  110. char *ifname, *mode;
  111. {
  112.     int cntr, filedescr, i, inword;
  113.     char c, t, temp;
  114.  
  115.     if ((filedescr = fopen(ifname,inbuf)) == ERROR) {
  116.        error(INPFERR);
  117.     }
  118.  
  119.     bufpntr = rambuf; charcntr = RESET;
  120.     switch (*mode) {
  121.  
  122.     case COMPRESS:
  123.  
  124.        inword = FALSE; i = RESET;
  125.  
  126.        do {
  127.            c = getciobuf();
  128.            while ((c == SPACE || c == LF || c == TAB) &&
  129.                   (inword == TRUE)) {
  130.               strbuf[i] = NULL; rword(); inword = FALSE;
  131.            }
  132.  
  133.            if (inword == FALSE) {
  134.               strbuf[0] = wspace(c);
  135.               i = 1; inword = TRUE;
  136.            }
  137.            else {
  138.               i += 1; strbuf[i-1] = c; inword = TRUE;
  139.            }
  140.  
  141.        } while (c != CPM_EOF);
  142.        *bufpntr = c; charcntr += 1; break;
  143.  
  144.     case EXPAND:
  145.  
  146.        do {
  147.            i = RESET;
  148.  
  149.            if ((c = getc(inbuf)) >= LLIMIT && c <= HLIMIT) {
  150.               *bufpntr++ = c; charcntr += 1;
  151.            }
  152.            else if (c > HLIMIT) { t = c - OFFSET1;
  153.               while ((c = wrdbuf[t][i++]) != NULL && c != INT_EOS) {
  154.                  *bufpntr++ = c; charcntr += 1;
  155.               }
  156.            }
  157.            else switch (c) {
  158.  
  159.            case RCODE:
  160.               cntr = getc(inbuf); c = getc(inbuf);
  161.               for (i = 0; i < cntr; ++i) {
  162.              if (c == LF) {
  163.                 *bufpntr++ = CR; charcntr += 1;
  164.              }
  165.              *bufpntr++ = c; charcntr += 1;
  166.               }
  167.               break;
  168.            case TAB:
  169.               *bufpntr++ = c; charcntr += 1; break;
  170.            case LF:
  171.               *bufpntr++ = CR; *bufpntr++ = c;
  172.               charcntr += 2;
  173.               if ((c == LF) && (charcntr >= TOPBUF)) {
  174.                 wrbuf(); bufpntr = rambuf; charcntr = RESET;
  175.               }
  176.               break;
  177.            case CPM_EOF:
  178.               *bufpntr = c; charcntr += 1; break;
  179.            default:
  180.               if (c < TAB) t = c - OFFSET2;
  181.               else t = (c < CPM_EOF) ? c - OFFSET3 : c - OFFSET4;
  182.               while ((c = wrdbuf[t][i++]) != NULL && c != INT_EOS) {
  183.              *bufpntr++ = c; charcntr += 1;
  184.               }
  185.               break;
  186.            }
  187.  
  188.        } while (c != CPM_EOF);
  189.        break;
  190.  
  191.     default: error(SWITERR); break;
  192.     }
  193.  
  194.     if (close(filedescr) == ERROR) error(CLOSERR);
  195. }
  196.  
  197. /*
  198. **    process white space
  199. */
  200. wspace(c)
  201. char c;
  202. {
  203.     int cntr, i, rflag;
  204.     char temp;
  205.  
  206.     temp = c; rflag = RESET; cntr = 1;
  207.  
  208.        do {
  209.            while ((c = getciobuf()) == temp) {
  210.               rflag = SET; cntr += 1;
  211.            }
  212.  
  213.            switch (cntr) {
  214.  
  215.            case 1:
  216.               *bufpntr++ = temp; temp = c; charcntr += 1; break;
  217.            case 2:
  218.            case 3:
  219.               for (i = 0; i < cntr; i++) {
  220.              *bufpntr++ = temp; charcntr += 1;
  221.               }
  222.               rflag = RESET; cntr = 1; temp = c; break;
  223.            default:
  224.               *bufpntr++ = RCODE; *bufpntr++ = cntr;
  225.               *bufpntr++ = temp; charcntr += 3;
  226.               rflag = RESET; cntr = 1; temp = c; break;
  227.            }
  228.  
  229.        } while (c == SPACE || c == LF || c == TAB);
  230.        return (c);
  231. }
  232.  
  233. /*
  234. **    process words
  235. */
  236. rword()
  237. {
  238.     int cntr, i, j, rflag; i = RESET;
  239.     char c, temp; temp = strbuf[0];
  240.  
  241.     if (strbuf[1] == NULL) {
  242.        *bufpntr++ = strbuf[0]; charcntr += 1; return;
  243.     }
  244.  
  245.    switch (strbuf[0]) {        /* optimize search time    */
  246.  
  247.    case 'A': i = 0  ; j = 3  ; break; case 'B': i = 4  ; j = 5  ; break;
  248.    case 'C': i = 6  ; j = 15 ; break; case 'D': i = 16 ; j = 27 ; break;
  249.    case 'E': i = 28 ; j = 31 ; break; case 'F': i = 32 ; j = 34 ; break;
  250.    case 'G': i = 35 ; j = 38 ; break; case 'I': i = 39 ; j = 44 ; break;
  251.    case 'J': i = 45 ; j = 49 ; break; case 'L': i = 50 ; j = 56 ; break;
  252.    case 'M': i = 57 ; j = 59 ; break; case 'N': i = 60 ; j = 60 ; break;
  253.    case 'O': i = 61 ; j = 67 ; break; case 'P': i = 68 ; j = 71 ; break;
  254.    case 'R': i = 72 ; j = 84 ; break; case 'S': i = 85 ; j = 92 ; break;
  255.    case 'T': i = 93 ; j = 95 ; break; case 'U': i = 96 ; j = 97 ; break;
  256.    case 'V': i = 98 ; j = 98 ; break; case 'W': i = 99 ; j = 101; break;
  257.    case 'X': i = 102; j = 103; break; case 'a': i = 104; j = 107; break;
  258.    case 'b': i = 108; j = 108; break; case 'c': i = 109; j = 110; break;
  259.    case 'd': i = 111; j = 112; break; case 'e': i = 113; j = 114; break;
  260.    case 'f': i = 115; j = 117; break; case 'g': i = 118; j = 119; break;
  261.    case 'i': i = 120; j = 125; break; case 'n': i = 126; j = 126; break;
  262.    case 'o': i = 127; j = 130; break; case 'p': i = 131; j = 132; break;
  263.    case 'r': i = 133; j = 134; break; case 's': i = 135; j = 136; break;
  264.    case 't': i = 137; j = 140; break; case 'u': i = 141; j = 142; break;
  265.    case 'w': i = 143; j = 145; break;
  266.  
  267.            default: i = 146; j = STRCOUNT; break;
  268.    }
  269.  
  270.     do {
  271.        if ((compare(strbuf,wrdbuf[i])) == TRUE) {
  272.        if (i <= BELL) i += OFFSET2;
  273.        else if (i >= FS) i += OFFSET1;
  274.             else if (i <= SYN) i += OFFSET3;
  275.                  else i += OFFSET4;
  276.        *bufpntr++ = i; charcntr += 1; return;
  277.        }
  278.     } while (i++ < j);
  279.  
  280. /*
  281. **    process non-reserved words
  282. */
  283.     i = RESET; temp = c; rflag = RESET; cntr = 1;
  284.  
  285.     do {
  286.         while ((c = strbuf[++i]) == temp) {
  287.            rflag = SET; cntr += 1;
  288.         }
  289.  
  290.         switch (cntr) {
  291.  
  292.         case 1:
  293.            *bufpntr++ = temp; temp = c; charcntr += 1; break;
  294.         case 2:
  295.         case 3:
  296.            for (j = 0; j < cntr; j++) {
  297.               *bufpntr++ = temp; charcntr += 1;
  298.            }
  299.            rflag = RESET; cntr = 1; temp = c; break;
  300.         default:
  301.            *bufpntr++ = RCODE; *bufpntr++ = cntr;
  302.            *bufpntr++ = temp; charcntr += 3;
  303.            rflag = RESET; cntr = 1; temp = c; break;
  304.         }
  305.  
  306.     } while (c != NULL);
  307. }
  308.  
  309. /*
  310. **    compar